import threading

class Channel:

	# dictionary of (name, agent_object) of agents connected to the channel
	agents = {}

	printLock = threading.Lock()

	def __init__(self, agents):
		self.agents = dict(zip(map(lambda x: x.name, agents), agents))

	def agentCount(self):
		return len(self.agents)

	def connect(self, agent):
		agents[agent.name] = agent

	def disconnect(self, agent):
		if agent.name in agents.keys():
			del agents[agent.name]

	# sends a message to an agent
	def sendMessage(self, src_name, dest_name, message):
		self.printLock.acquire()
		self.printLock.release()
		self.Receiver(self.agents[dest_name], src_name, message).start()

	# sends a message to all agents connected to the channel
	def bcastMessage(self, src_name, message):
		for agent in self.agents.values():
			if agent.name != src_name:
				self.Receiver(agent, src_name, message).start()

	# receiver thread that does the message handling for an agent
	class Receiver(threading.Thread):
		def __init__(self, agent, src_name, message): 
			threading.Thread.__init__(self)
			self.agent = agent
			self.src_name = src_name
			self.message = message

		def run(self):
			self.agent.recvMessage(self.src_name, self.message)
			

# generic message object
class Message:
	def __init__(self, type, arg1=None, arg2=None, arg3=None):
		self.type = type
		self.arg1 = arg1
		self.arg2 = arg2
		self.arg3 = arg3
